﻿/**
 * @package ZMenFM.Utils
 * @brief ZMWindowShadow
 * 窗口阴影类。（基于原窗口大小，而非将原窗口变小）
 * 原理：在父窗口四周建立四个影子窗体。
 * @todo: 将就着用，谁来帮忙优化？
 * 
 * @author XadillaX (admin#xcoder.in)
 * @date 07/21/2012
 * 
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Interop;
using System.Diagnostics;

using ZMenFM.Utils.Img;
using ZMenFM.Utils.Interop;

namespace ZMenFM.Utils.UI
{
    public class ZMWindowShadowImages
    {
        protected static Dictionary<String, ImageSource> Images = new Dictionary<string,ImageSource>();

        static public Decorator GetShodowBorder(String name)
        {
            name = name.ToUpper();

            try
            {
                if (!Images.ContainsKey(name))
                {
                    BitmapImage img = new BitmapImage(ZMUtilsImgLoader.GetImageUri("Shadow/" + name));
                    if (null == img) return null;

                    Images[name] = img;
                }

                Border border = new Border();
                border.CornerRadius = new CornerRadius(0);
                border.Background = new ImageBrush(Images[name]);

                return border;
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);

                return null;
            }
        }
    }

    public class ZMWindowShadow
    {
        private Window ParentWindow = null;

        private Window m_wndT;
        private Window m_wndL;
        private Window m_wndB;
        private Window m_wndR;
        private Window m_wndLT;
        private Window m_wndLB;
        private Window m_wndRT;
        private Window m_wndRB;

        private Window[] Windows = new Window[8];

        private int c_edgeWndSize = 24;
        private bool ActiveMode = true;

        #region 初始化函数
        /// <summary>
        /// 创建空窗口（用于影子窗体）
        /// </summary>
        /// <returns></returns>
        private static Window CreateTransparentWindow()
        {
            Window wnd = new Window();
            wnd.AllowsTransparency = true;
            wnd.ShowInTaskbar = false;
            wnd.WindowStyle = WindowStyle.None;
            wnd.Background = null;
            wnd.Width = wnd.Height = 0;

            IntPtr Handle = new WindowInteropHelper(wnd).EnsureHandle();
            int extendedStyle = NativeMethods.GetWindowLong(Handle, GWL.EXSTYLE);
            NativeMethods.SetWindowLong(Handle, GWL.EXSTYLE, extendedStyle
                //鼠标穿透
                | WS.EX.TRANSPARENT);

            return wnd;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="window">父窗口</param>
        public ZMWindowShadow(Window window)
        {
            ParentWindow = window;

            InitializeSurrounds();

            ParentWindow.LocationChanged += OnParentWindowChanged;
            ParentWindow.SizeChanged += OnParentWindowChanged;
            ParentWindow.StateChanged += OnParentStateChanged;
            ParentWindow.Closed += OnParentClosed;
            ParentWindow.Activated += OnParentActive;
            ParentWindow.Deactivated += OnParentActive;
        }

        /// <summary>
        /// 初始化四周影子窗口
        /// </summary>
        private void InitializeSurrounds()
        {
            m_wndT = CreateTransparentWindow(); Windows[0] = m_wndT;
            m_wndL = CreateTransparentWindow(); Windows[1] = m_wndL;
            m_wndB = CreateTransparentWindow(); Windows[2] = m_wndB;
            m_wndR = CreateTransparentWindow(); Windows[3] = m_wndR;
            m_wndLT = CreateTransparentWindow(); Windows[4] = m_wndLT;
            m_wndLB = CreateTransparentWindow(); Windows[5] = m_wndLB;
            m_wndRT = CreateTransparentWindow(); Windows[6] = m_wndRT;
            m_wndRB = CreateTransparentWindow(); Windows[7] = m_wndRB;

            SetSurroundShadows(ParentWindow.IsActive);
        }
        #endregion

        #region 父窗口响应函数
        /// <summary>
        /// 窗体位置变化。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OnParentWindowChanged(Object sender, EventArgs e)
        {
            m_wndT.Width = ParentWindow.Width;
            m_wndT.Height = c_edgeWndSize;
            m_wndT.Left = ParentWindow.Left;
            m_wndT.Top = ParentWindow.Top - m_wndT.Height;

            m_wndL.Width = c_edgeWndSize;
            m_wndL.Height = ParentWindow.Height;
            m_wndL.Left = ParentWindow.Left - m_wndL.Width;
            m_wndL.Top = ParentWindow.Top;

            m_wndB.Width = ParentWindow.Width;
            m_wndB.Height = c_edgeWndSize;
            m_wndB.Left = ParentWindow.Left;
            m_wndB.Top = ParentWindow.Top + ParentWindow.Height;

            m_wndR.Width = c_edgeWndSize;
            m_wndR.Height = ParentWindow.Height;
            m_wndR.Left = ParentWindow.Left + ParentWindow.Width;
            m_wndR.Top = ParentWindow.Top;

            m_wndLT.Width = m_wndLT.Height = 24;
            m_wndLT.Left = ParentWindow.Left - 24;
            m_wndLT.Top = ParentWindow.Top - 24;

            m_wndLB.Width = m_wndLB.Height = 24;
            m_wndLB.Left = ParentWindow.Left - 24;
            m_wndLB.Top = ParentWindow.Top + ParentWindow.Height;

            m_wndRT.Width = m_wndRT.Height = 24;
            m_wndRT.Left = ParentWindow.Left + ParentWindow.Width;
            m_wndRT.Top = ParentWindow.Top - 24;

            m_wndRB.Width = m_wndRB.Height = 24;
            m_wndRB.Left = ParentWindow.Left + ParentWindow.Width;
            m_wndRB.Top = ParentWindow.Top + ParentWindow.Height;

            UpdateShadowState();
        }

        /// <summary>
        /// 窗体状态变化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OnParentStateChanged(Object sender, EventArgs e)
        {
            UpdateShadowState();
        }

        /// <summary>
        /// 父窗口关闭
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OnParentClosed(Object sender, EventArgs e)
        {
            m_wndT.Close();
            m_wndL.Close();
            m_wndB.Close();
            m_wndR.Close();
            m_wndLT.Close();
            m_wndLB.Close();
            m_wndRT.Close();
            m_wndRB.Close();
        }

        /// <summary>
        /// 激活父窗口
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void OnParentActive(Object sender, EventArgs e)
        {
            SetSurroundShadows(ParentWindow.IsActive);
            UpdateShadowState();
        }
        #endregion

        #region 功能函数
        /// <summary>
        /// 设置阴影
        /// </summary>
        /// <param name="active">是否活动</param>
        private void SetSurroundShadows(Boolean active = true)
        {
            ActiveMode = active;
            if (active)
            {
                m_wndT.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWTOP.PNG");
                m_wndL.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWLEFT.PNG");
                m_wndB.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWBOTTOM.PNG");
                m_wndR.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWRIGHT.PNG");

                m_wndLT.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWTOPLEFT.png");
                m_wndLB.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWBOTTOMLEFT.png");
                m_wndRT.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWTOPRIGHT.png");
                m_wndRB.Content = ZMWindowShadowImages.GetShodowBorder("ACTIVESHADOWBOTTOMRIGHT.png");
            }
            else
            {
                m_wndT.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWTOP.PNG");
                m_wndL.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWLEFT.PNG");
                m_wndB.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWBOTTOM.PNG");
                m_wndR.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWRIGHT.PNG");

                m_wndLT.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWTOPLEFT.png");
                m_wndLB.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWBOTTOMLEFT.png");
                m_wndRT.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWTOPRIGHT.png");
                m_wndRB.Content = ZMWindowShadowImages.GetShodowBorder("INACTIVESHADOWBOTTOMRIGHT.png");
            }
        }

        /// <summary>
        /// 更新阴影
        /// </summary>
        public void UpdateShadowState()
        {
            /** 要隐藏 */
            if (ParentWindow.WindowState != WindowState.Normal)
            {
                for (int i = 0; i < 8; i++) Windows[i].Hide();
            }
            /** 要显示 */
            else
            {
                IntPtr OwnerHandle = new WindowInteropHelper(ParentWindow).EnsureHandle();

                for (int i = 0; i < 8; i++)
                {
                    Windows[i].Show();

                    IntPtr Handle = new WindowInteropHelper(Windows[i]).EnsureHandle();
                    NativeMethods.SetWindowPos(Handle, OwnerHandle, 0, 0, 0, 0, SWP.SHOWWINDOW | SWP.NOACTIVATE | SWP.NOOWNERZORDER | SWP.NOREPOSITION | SWP.NOMOVE | SWP.NOSIZE);
                }
            }
        }
        #endregion
    }
}
